//  Inside Microsoft Exchange 2007 Web Services 
//  Chapter 17
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.  
//  All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Text;
using ProxyHelpers.EWS;

namespace UsingThePushNotificationClient
{
    // Using Push Notifications and the PushNotificationClient (Listing 17-23)
    //
    class Program
    {
        private static ExchangeServiceBinding binding;

        /// <summary>
        /// Main entry point 
        /// </summary>
        /// <param name="args">args</param>
        /// 
        static void Main(string[] args)
        {
            // STEP 1: Create our binding
            //
            binding = new ExchangeServiceBinding();
            binding.Url = "https://yourServer/ews/Exchange.asmx";
            binding.UseDefaultCredentials = true;

            // STEP 2: Create our Push subscription. Note that the PushNotificationsClient
            // listens on http://{host:port}/PushNotificationsClient
            //
            string subscriptionId;
            string watermark;
            CreatePushSubscription(
                          binding,
                          new NotificationEventTypeType[] {
                          NotificationEventTypeType.CreatedEvent },
                          new BaseFolderIdType[] { 
                          new DistinguishedFolderIdType(
                                DistinguishedFolderIdNameType.drafts) },
                          @"http://yourClient:8081/PushNotificationsClient",
                          5,
                          out subscriptionId,
                          out watermark);

            // STEP 3: Create the listener and begin listening
            //
            PushNotificationClient.PushNotificationClient c = new
                  PushNotificationClient.PushNotificationClient(
                          8081, /* port */
                          HandleNotificationReceived /* delegate */);
            c.StartListening();
            Console.WriteLine("Listening");

            // STEP 4: Create a message in the drafts folder
            //
            CreateItemType createItemRequest = new CreateItemType();
            createItemRequest.MessageDisposition = MessageDispositionType.SaveOnly;
            createItemRequest.MessageDispositionSpecified = true;
            MessageType message = new MessageType();
            message.Subject = "Testing Push Notifications";
            createItemRequest.Items = new NonEmptyArrayOfAllItemsType();
            createItemRequest.Items.Items = new ItemType[] { message };
            binding.CreateItem(createItemRequest);

            // STEP 7: Close the push notifications client. See delegate below for steps
            // 5 and 6.
            //
            Console.WriteLine("Press any key to stop listening");
            Console.ReadLine();
            c.StopListening();
        }

        /// <summary>
        /// Delegate for handling notifications from EWS
        /// </summary>
        /// <param name="sender">PushNotificationsClient</param>
        /// <param name="eventData">Notification</param>
        /// <returns>Notification response (ok or unsubscribe)</returns>
        ///
        private static PushNotificationClient.NotificationResponse HandleNotificationReceived(
                  object sender,
                  SendNotificationResponseMessageType eventData)
        {
            // Write out the watermark for fun
            //
            Console.WriteLine(eventData.Notification.Items[0].Watermark);

            // STEP 5: Call GetItem and write out the subject of the created message
            //
            BaseObjectChangedEventType createdEvent = eventData.Notification.Items[0] as
                     BaseObjectChangedEventType;
            ItemIdType modifiedItemId = createdEvent.Item as ItemIdType;

            GetItemType getItemRequest = new GetItemType();
            getItemRequest.ItemShape = new ItemResponseShapeType(
                      DefaultShapeNamesType.Default);
            getItemRequest.ItemIds = new BaseItemIdType[] { modifiedItemId };
            GetItemResponseType getItemResponse = binding.GetItem(getItemRequest);
            ItemInfoResponseMessageType responseMessage =
                  getItemResponse.ResponseMessages.Items[0] as ItemInfoResponseMessageType;

            Console.WriteLine("Item created in drafts folder: " +
                  responseMessage.Items.Items[0].Subject);

            // STEP 6: Unsubscribe
            //
            return PushNotificationClient.NotificationResponse.Unsubscribe;
        }

        /// <summary>
        /// Create a push subscription (Listing 17-18)
        /// </summary>
        /// <param name="binding">ExchangeServiceBinding to use for the call</param>
        /// <param name="eventTypes">Event types to subscribe to</param>
        /// <param name="subscriptionFolders">Folder to look for changes in</param>
        /// <param name="clientURL">URL of the client-side web service</param>
        /// <param name="statusFrequencyInMinutes">Status frequency</param>
        /// <param name="subscriptionId">OUT new subscription Id</param>
        /// <param name="watermark">OUT new watermark</param>
        /// 
        public static void CreatePushSubscription(
                                   ExchangeServiceBinding binding,
                                   NotificationEventTypeType[] eventTypes,
                                   BaseFolderIdType[] subscriptionFolders,
                                   string clientURL,
                                   int statusFrequencyInMinutes,
                                   out string subscriptionId,
                                   out string watermark)
        {
            // Call the overloaded constructor
            //
            PushSubscriptionRequestType pushSubscription =
                     new PushSubscriptionRequestType(
                                  subscriptionFolders,
                                  eventTypes,
                                  statusFrequencyInMinutes,
                                  clientURL,
                                  null /* A new Subscription so no watermark */);

            SubscribeType subscribeRequest = new SubscribeType();
            subscribeRequest.Item = pushSubscription;
            SubscribeResponseType subscribeResponse = binding.Subscribe(subscribeRequest);

            // We have a response. Now we need to parse it to get the SubscriptionId and 
            // the Watermark
            //
            SubscribeResponseMessageType subscribeResponseMessage =
                  subscribeResponse.ResponseMessages.Items[0] as
                       SubscribeResponseMessageType;

            if (subscribeResponseMessage.ResponseCode == ResponseCodeType.NoError)
            {
                subscriptionId = subscribeResponseMessage.SubscriptionId;
                watermark = subscribeResponseMessage.Watermark;
            }
            else
            {
                // We received an error in the response
                throw new Exception(subscribeResponseMessage.MessageText);
            }
        }
    }
}
